package com.cube.truthseer.service.impl;


import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cube.truthseer.common.entity.enums.ResultCode;
import com.cube.truthseer.common.entity.vo.ResultMessage;
import com.cube.truthseer.common.exception.BadRequestException;
import com.cube.truthseer.common.exception.ForbiddenException;
import com.cube.truthseer.common.exception.ServiceException;
import com.cube.truthseer.common.minio.MinIOUtil;
import com.cube.truthseer.common.properties.JWTTokenProperties;
import com.cube.truthseer.common.security.AuthUser;
import com.cube.truthseer.common.security.context.UserContext;
import com.cube.truthseer.common.security.enums.UserEnums;
import com.cube.truthseer.common.security.token.Token;
import com.cube.truthseer.common.security.token.TokenUtil;
import com.cube.truthseer.common.security.token.base.AbstractTokenGenerate;
import com.cube.truthseer.common.utils.ResultUtil;
import com.cube.truthseer.common.utils.StringUtil;
import com.cube.truthseer.entity.bucket.enums.BucketStatus;
import com.cube.truthseer.entity.bucket.po.Bucket;
import com.cube.truthseer.entity.user.constants.UserConstants;
import com.cube.truthseer.entity.user.dto.LoginFormDTO;
import com.cube.truthseer.entity.user.dto.LoginUserDTO;
import com.cube.truthseer.entity.user.dto.UserFormDto;
import com.cube.truthseer.entity.user.enums.UserStatus;
import com.cube.truthseer.mapper.UserMapper;
import com.cube.truthseer.service.IBucketService;
import com.cube.truthseer.service.ICodeService;
import com.cube.truthseer.service.IUserService;
import io.minio.MinioClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import com.cube.truthseer.entity.user.po.User;
import org.springframework.transaction.annotation.Transactional;

import static com.cube.truthseer.entity.user.constants.UserErrorInfo.Msg.*;
import static com.cube.truthseer.entity.user.constants.UserErrorInfo.Msg.USER_FROZEN;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zw
 * @since 2024-03-09
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    private final ICodeService codeService;
    private final UserMapper userMapper;
    private final TokenUtil tokenUtil;
    private final JWTTokenProperties tokenProperties;
    private final PasswordEncoder passwordEncoder;
    private final MinIOUtil minIOUtil;
    private final IBucketService bucketService;
//    private final AbstractTokenGenerate<AuthUser> tokenGenerate;
@Transactional
    @Override
    public ResultMessage<Token> queryUser(LoginFormDTO loginDTO) {
        //1.判断登录方式
        Integer type = loginDTO.getType();
        User user = null;
        //2.邮箱和密码一起登录
        if(type == 1){
            user = loginByPw(loginDTO);
        }
        //3.验证码登录
        if(type == 2){
            user = loginByVerifyCode(loginDTO.getEmail(),loginDTO.getCode());
        }
        //4.错误的登录方式
        if(user == null){
            throw new BadRequestException(ILLEGAL_LOGIN_TYPE);
        }
        LoginUserDTO userDTO= new LoginUserDTO();
//        userDTO.setUserId(user.getUserId());
//        userDTO.setBucketId(user.getBucketId());
        AuthUser authUser = new AuthUser(user.getName(), user.getUserId(), UserEnums.USER,true);
        Token token = tokenUtil.createToken(authUser);
        return ResultUtil.data(token);
//        return ResultUtil.data(token);
    }
    private User loginByVerifyCode(String email, String code) {
        //1.校验验证码
        codeService.verifyCode(email, code,1);
        //2.根据邮箱查询
        User user = lambdaQuery().eq(User::getEmail,email).one();
        if(user == null){
            throw new BadRequestException(EMAIL_NOT_EXISTS);
        }
        //3.校验是否已注销
        if(user.getIsDelete()== UserStatus.FROZEN){
            throw new ForbiddenException(USER_FROZEN);
        }
        return user;

    }

    private User loginByPw(LoginFormDTO loginDTO) {
        //1.数据校验
        String email = loginDTO.getEmail();
        if(StringUtil.isBlank(email)){
            throw new BadRequestException(INVALID_UN);
        }
        //2.根据用户名或者是手机号码查询
        User user = lambdaQuery().eq(User::getEmail,loginDTO.getEmail()).one();
        if(user == null){
            throw new BadRequestException(EMAIL_NOT_EXISTS);
        }
        //3.校验是否已注销
        if(user.getIsDelete()==UserStatus.FROZEN){
            throw new ForbiddenException(USER_FROZEN);
        }
//        //4.校验密码
//        if (!passwordEncoder.matches(loginDTO.getPassword(), user.getPassword())) {
//            throw new BadRequestException(INVALID_UN_OR_PW);
//        }
        return user;

    }
    @Transactional
    @Override
    public ResultMessage<String> saveUser(UserFormDto userFormDto) {

        User user=new User();
        user.setEmail(userFormDto.getEmail());
        log.info("passwordEncoder.encode(user.getPassword()):"+passwordEncoder.encode(userFormDto.getPassword()));
        user.setPassword(passwordEncoder.encode(userFormDto.getPassword()));
        user.setIsDelete(UserStatus.of(0));
//        user.setType(UserType.USER.getValue());//设置为用户
        //1.验证用户的验证码
       codeService.verifyCode(userFormDto.getEmail(),userFormDto.getCode(),2);
        //2/保存用户
        System.out.println(user);
        save(user);
        //3.创建桶名
        String bucketName = minIOUtil.existBucket(String.valueOf(user.getUserId()));
        Bucket bucket = new Bucket();
        bucket.setBucketName(bucketName);
        bucket.setUserId(user.getUserId());
        bucket.setStatus(BucketStatus.NORMAL);
        //3.保存桶
        bucketService.save(bucket);
        //4.这里我要求要保存用户的id，我不会，这里要人补充代码

        return ResultUtil.success(ResultCode.SUCCESS);
    }

    @Override
    public ResultMessage<User> getUserInfo(Long userId) {
        User user = userMapper.selectById(userId);
        if(user == null){
            throw new ServiceException(ResultCode.USER_NOT_EXIST);
        }
        return ResultUtil.data(user);
    }
}
